#include "SWF.h"
#include "SWFTag.h"
#include "tags/TagDoABC.h"

SWF::~SWF()
{
	for (auto frame : frames)
	{
		frame->release();
	}
}

SWF::SWF()
	: fileAttributes(nullptr)
	, enableDebugger(nullptr)
	, enableDebugger2(nullptr)
	, metadata(nullptr)
	, scriptLimits(nullptr)
	, setBackgroundColor(nullptr)
	, defineSceneAndFrameLabelData(nullptr)
	, productInfo(nullptr)
	, protect(nullptr)
	, compression(SWFCompression::Zlib)
	, version(13)
	, frameRate(30)
	, width(400)
	, height(300)
{

}

void SWF::getImageTags( std::vector<SWFTag*>& output ) const
{
	for (SWFFrame* frame : frames)
	{
		for (DefineTag* tag : frame->bitmaps)
		{
			output.push_back(tag);
		}
	}
}

void SWF::getShapeTags( std::vector<SWFTag*>& output ) const
{
	for (SWFFrame* frame : frames)
	{
		for (DefineTag* tag : frame->shapes)
		{
			output.push_back(tag);
		}
	}
}

void SWF::getSpriteTags( std::vector<SWFTag*>& output ) const
{
	for (SWFFrame* frame : frames)
	{
		for (DefineTag* tag : frame->sprites)
		{
			output.push_back(tag);
		}
	}
}

void SWF::getFontTags( std::vector<SWFTag*>& output ) const
{
	for (SWFFrame* frame : frames)
	{
		for (DefineTag* tag : frame->fonts)
		{
			output.push_back(tag);
		}
	}
}

void SWF::getTextTags( std::vector<SWFTag*>& output ) const
{
	for (SWFFrame* frame : frames)
	{
		for (DefineTag* tag : frame->texts)
		{
			output.push_back(tag);
		}
	}
}

void SWF::getButtonTags( std::vector<SWFTag*>& output ) const
{
	for (SWFFrame* frame : frames)
	{
		for (DefineTag* tag : frame->buttons)
		{
			output.push_back(tag);
		}
	}
}

void SWF::getOtherTags( std::vector<SWFTag*>& output ) const
{
	if (this->fileAttributes)
		output.push_back(this->fileAttributes);
	if (this->metadata)
		output.push_back(this->metadata);
	if (this->scriptLimits)
		output.push_back(this->scriptLimits);
	if (this->setBackgroundColor)
		output.push_back(this->setBackgroundColor);
	if (this->productInfo)
		output.push_back(this->productInfo);
	if (this->protect)
		output.push_back(this->protect);
	if (this->enableDebugger)
		output.push_back(this->enableDebugger);
	if (this->enableDebugger2)
		output.push_back(this->enableDebugger2);

	for (SWFFrame* frame : frames)
	{
		for (DefineTag* tag : frame->exportDefs)
		{
			output.push_back(tag);
		}
		for (DefineTag* tag : frame->sounds)
		{
			output.push_back(tag);
		}
		for (DefineTag* tag : frame->binaryDatas)
		{
			output.push_back(tag);
		}
	}
}

void SWF::addFrame(SWFFrame* frame)
{
	frame->retain();
	frames.push_back(frame);
}

void SWF::getAllFrames(std::vector<SWFFrame*>& output)
{
	output.insert(output.begin(), frames.begin(), frames.end());
}

size_t SWF::getFrameCount() const
{
	return frames.size();
}

void SWF::setFileAttributesTag(TagFileAttributes* tag)
{
	SAFE_RELEASE(fileAttributes);
	fileAttributes = tag;
	SAFE_RETAIN(fileAttributes);
}

void SWF::setMetadataTag(TagMetadata* tag)
{
	SAFE_RELEASE(metadata);
	metadata = tag;
	SAFE_RETAIN(metadata);
}

void SWF::setBackgroundColorTag(TagSetBackgroundColor* tag)
{
	SAFE_RELEASE(setBackgroundColor);
	setBackgroundColor = tag;
	SAFE_RETAIN(setBackgroundColor);
}

void SWF::setScriptLimitsTag(TagScriptLimits* tag)
{
	SAFE_RELEASE(scriptLimits);
	scriptLimits = tag;
	SAFE_RETAIN(scriptLimits);
}

void SWF::setEnableDebuggerTag(TagEnableDebugger* tag)
{
	SAFE_RELEASE(enableDebugger);
	enableDebugger = tag;
	SAFE_RETAIN(enableDebugger);
}

void SWF::setEnableDebuggerTag2(TagEnableDebugger2* tag)
{
	SAFE_RELEASE(enableDebugger2);
	enableDebugger2 = tag;
	SAFE_RETAIN(enableDebugger2);
}

void SWF::setProductInfoTag(TagProductInfo* tag)
{
	SAFE_RELEASE(productInfo);
	productInfo = tag;
	SAFE_RETAIN(productInfo);
}

void SWF::setProtectTag(TagProtect* tag)
{
	SAFE_RELEASE(protect);
	protect = tag;
	SAFE_RETAIN(protect);
}

SWFFrame::SWFFrame()
	: frameLabel(nullptr)
	, symbolClass(nullptr)
{

}

SWFFrame::~SWFFrame()
{
	if (frameLabel)
		frameLabel->release();
	frameLabel = nullptr;
	if (symbolClass)
		symbolClass->release();
	symbolClass = nullptr;
	for (SWFTag* tag : exportDefs)
		tag->release();
	for (SWFTag* tag : doABCs)
		tag->release();
	for (SWFTag* tag : imports)
		tag->release();
	for (SWFTag* tag : controlTags)
		tag->release();

	for (SWFTag* tag : buttons)
		tag->release();
	for (SWFTag* tag : binaryDatas)
		tag->release();
	for (SWFTag* tag : bitmaps)
		tag->release();
	for (SWFTag* tag : fonts)
		tag->release();
	for (SWFTag* tag : morphShapes)
		tag->release();
	for (SWFTag* tag : shapes)
		tag->release();
	for (SWFTag* tag : sounds)
		tag->release();
	for (SWFTag* tag : sprites)
		tag->release();
	for (SWFTag* tag : texts)
		tag->release();
}

void SWFFrame::getAllDefineTags(std::vector<DefineTag*>& tags)
{
	tags.insert(tags.end(), buttons.begin(), buttons.end());
	tags.insert(tags.end(), binaryDatas.begin(), binaryDatas.end());
	tags.insert(tags.end(), bitmaps.begin(), bitmaps.end());
	tags.insert(tags.end(), fonts.begin(), fonts.end());
	tags.insert(tags.end(), morphShapes.begin(), morphShapes.end());
	tags.insert(tags.end(), shapes.begin(), shapes.end());
	tags.insert(tags.end(), sounds.begin(), sounds.end());
	tags.insert(tags.end(), sprites.begin(), sprites.end());
	tags.insert(tags.end(), texts.begin(), texts.end());
	tags.insert(tags.end(), exportDefs.begin(), exportDefs.end());
}

void SWFFrame::addControlTag(SWFTag* tag)
{
	tag->retain();
	this->controlTags.push_back(tag);
}

void SWFFrame::addButtonTag(DefineTag* tag)
{
	tag->retain();
	this->buttons.push_back(tag);
}

void SWFFrame::addBinaryDataTag(DefineTag* tag)
{
	tag->retain();
	this->binaryDatas.push_back(tag);
}

void SWFFrame::addBitmapTag(DefineTag* tag)
{
	tag->retain();
	this->bitmaps.push_back(tag);
}

void SWFFrame::addFontTag(DefineTag* tag)
{
	tag->retain();
	this->fonts.push_back(tag);
}

void SWFFrame::addMorphShapeTag(DefineTag* tag)
{
	tag->retain();
	this->morphShapes.push_back(tag);
}

void SWFFrame::addShapeTag(DefineTag* tag)
{
	tag->retain();
	this->shapes.push_back(tag);
}

void SWFFrame::addSoundTag(DefineTag* tag)
{
	tag->retain();
	this->sounds.push_back(tag);
}

void SWFFrame::addSpriteTag(DefineTag* tag)
{
	tag->retain();
	this->sprites.push_back(tag);
}

void SWFFrame::addTextTag(DefineTag* tag)
{
	tag->retain();
	this->texts.push_back(tag);
}

void SWFFrame::addDoABCTag(TagDoABC* tag)
{
	tag->retain();
	this->doABCs.push_back(tag);
}

void SWFFrame::addDefineTag(DefineTag* tag)
{
	tag->retain();
	this->exportDefs.push_back(tag);
}

void SWFFrame::setFrameLabel(TagFrameLabel* tag)
{
	SAFE_RELEASE(frameLabel);
	frameLabel = tag;
	SAFE_RETAIN(frameLabel);
}

void SWFFrame::setSymbolClass(TagSymbolClass* tag)
{
	SAFE_RELEASE(symbolClass);
	symbolClass = tag;
	SAFE_RETAIN(symbolClass);
}

void SWFFrame::getAllDoABCTags(std::vector<TagDoABC*>& output) const
{
	output.insert(output.end(), doABCs.begin(), doABCs.end());
}

void SWFFrame::getAllControlTags(std::vector<SWFTag*>& output) const
{
	output.insert(output.end(), controlTags.begin(), controlTags.end());
}
